home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / dosrcss.zip / RCSSYN.C < prev    next >
C/C++ Source or Header  |  1990-07-18  |  17KB  |  575 lines

  1. /*
  2.  *                     RCS file input
  3.  */
  4. #ifndef lint
  5. static char rcsid[]= "$Id: rcssyn.c,v 5.2 90/07/15 11:35:24 ROOT_DOS Release $ Purdue CS";
  6. #endif
  7. /*********************************************************************************
  8.  *                       Syntax Analysis.
  9.  *                       Keyword table
  10.  *                       Testprogram: define SYNDB
  11.  *                       Compatibility with Release 2: define COMPAT2
  12.  *********************************************************************************
  13.  */
  14.  
  15. /* Copyright (C) 1982, 1988, 1989 Walter Tichy
  16.    Distributed under license by the Free Software Foundation, Inc.
  17.  
  18. This file is part of RCS.
  19.  
  20. RCS is free software; you can redistribute it and/or modify
  21. it under the terms of the GNU General Public License as published by
  22. the Free Software Foundation; either version 1, or (at your option)
  23. any later version.
  24.  
  25. RCS is distributed in the hope that it will be useful,
  26. but WITHOUT ANY WARRANTY; without even the implied warranty of
  27. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  28. GNU General Public License for more details.
  29.  
  30. You should have received a copy of the GNU General Public License
  31. along with RCS; see the file COPYING.  If not, write to
  32. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  33.  
  34. Report problems and direct all questions to:
  35.  
  36.     rcs-bugs@cs.purdue.edu
  37.  
  38. */
  39.  
  40.  
  41. /* $Log:    rcssyn.c,v $
  42.  * Revision 5.2  90/07/15  11:35:24  ROOT_DOS
  43.  * DOS version of RCS 4.0 checked in for MODS
  44.  * by lfk@athena.mit.edu
  45.  * Also update to MSC 6.0
  46.  * 
  47.  * Revision 4.6  89/05/01  15:13:32  narten
  48.  * changed copyright header to reflect current distribution rules
  49.  * 
  50.  * Revision 4.5  88/11/08  12:00:37  narten
  51.  * changes from  eggert@sm.unisys.com (Paul Eggert)
  52.  * 
  53.  * Revision 4.5  88/08/09  19:13:21  eggert
  54.  * Allow cc -R; remove lint.
  55.  * 
  56.  * Revision 4.4  87/12/18  11:46:16  narten
  57.  * more lint cleanups (Guy Harris)
  58.  * 
  59.  * Revision 4.3  87/10/18  10:39:36  narten
  60.  * Updating version numbers. Changes relative to 1.1 actually relative to
  61.  * 4.1
  62.  * 
  63.  * Revision 1.3  87/09/24  14:00:49  narten
  64.  * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
  65.  * warnings)
  66.  * 
  67.  * Revision 1.2  87/03/27  14:22:40  jenkins
  68.  * Port to suns
  69.  * 
  70.  * Revision 1.1  84/01/23  14:50:40  kcs
  71.  * Initial revision
  72.  * 
  73.  * Revision 4.1  83/03/28  11:38:49  wft
  74.  * Added parsing and printing of default branch.
  75.  * 
  76.  * Revision 3.6  83/01/15  17:46:50  wft
  77.  * Changed readdelta() to initialize selector and log-pointer.
  78.  * Changed puttree to check for selector==DELETE; putdtext() uses DELNUMFORM.
  79.  *
  80.  * Revision 3.5  82/12/08  21:58:58  wft
  81.  * renamed Commentleader to Commleader.
  82.  *
  83.  * Revision 3.4  82/12/04  13:24:40  wft
  84.  * Added routine gettree(), which updates keeplock after reading the
  85.  * delta tree.
  86.  *
  87.  * Revision 3.3  82/11/28  21:30:11  wft
  88.  * Reading and printing of Suffix removed; version COMPAT2 skips the
  89.  * Suffix for files of release 2 format. Fixed problems with printing nil.
  90.  *
  91.  * Revision 3.2  82/10/18  21:18:25  wft
  92.  * renamed putdeltatext to putdtext.
  93.  *
  94.  * Revision 3.1  82/10/11  19:45:11  wft
  95.  * made sure getc() returns into an integer.
  96.  */
  97.  
  98.  
  99.  
  100. /*
  101. #define COMPAT2
  102. /* version COMPAT2 reads files of the format of release 2 and 3, but
  103.  * generates files of release 3 format. Need not be defined if no
  104.  * old RCS files generated with release 2 exist.
  105.  */
  106. /*
  107. #define SYNDB
  108. /* version SYNDB is for debugging the syntax analysis for RCS files.
  109.  * SYNDB performs additional error checks.
  110.  */
  111. /*
  112. #define SYNTEST
  113. /* version SYNTEST inputs a RCS file and then prints out its internal
  114.  * data structures.
  115. */
  116.  
  117. #include "rcsbase.h"
  118. extern FILE * finptr;        /*RCS input file*/
  119. extern char * getid();
  120. extern struct hshentry * getnum();
  121. extern int    getkey();
  122. extern int    getlex();
  123. extern        readstring();
  124. extern        savestring();
  125.  
  126. /* forward */
  127. char * getkeyval();
  128.  
  129. /* keyword table */
  130.  
  131. char Kaccess[]   = "access";
  132. char Kauthor[]   = "author";
  133. char Kbranch[]   = "branch";
  134. char Kbranches[] = "branches";
  135. char Kcomment[]  = "comment";
  136. char Kdate[]     = "date";
  137. char Kdesc[]     = "desc";
  138. char Khead[]     = "head";
  139. char Klocks[]    = "locks";
  140. char Klog[]      = "log";
  141. char Knext[]     = "next";
  142. char Kstate[]    = "state";
  143. char Kstrict[]   = "strict";
  144. #ifdef COMPAT2
  145. char Ksuffix[]   = "suffix";
  146. #endif
  147. char Ksymbols[]  = "symbols";
  148. char Ktext[]     = "text";
  149.  
  150. #define COMMLENGTH 20
  151. char              Commleader[COMMLENGTH];
  152. char            * Comment;
  153. struct access   * AccessList;
  154. struct access   * LastAccess;
  155. struct assoc    * Symbols;
  156. struct assoc    * LastSymbol;
  157. struct lock     * Locks;
  158. struct lock     * LastLock;
  159. int               StrictLocks;
  160. struct hshentry * Head;
  161. struct hshentry * Dbranch;
  162. int               TotalDeltas;
  163.  
  164.  
  165.  
  166. getadmin()
  167. /* Function: Reads an <admin> and initializes the globals
  168.  * AccessList, LastAccess, Symbols, LastSymbol,
  169.  * Locks, LastLock, StrictLocks, Head, Comment, TotalDeltas;
  170.  */
  171. {
  172.         register char   * id;
  173.         struct access   * newaccess;
  174.         struct assoc    * newassoc;
  175.         struct lock     * newlock;
  176.         struct hshentry * delta;
  177.  
  178.         Comment="";
  179.         AccessList=LastAccess=nil;
  180.         Symbols=LastSymbol=nil;
  181.         Locks=LastLock=nil;
  182.         Dbranch = Head = nil;
  183.         TotalDeltas=0;
  184.  
  185.         if (!getkey(Khead)) fatserror("Missing head");
  186.         Head=getnum();
  187. #       ifdef SYNDB
  188.         if (Head&&((countnumflds(Head->num)%2)!=0))
  189.                 serror("Delta number required for head");
  190. #       endif
  191.         if (!getlex(SEMI)) serror("Missing ';' after head");
  192.  
  193.         if (getkey(Kbranch)) { /* optional */
  194.                 Dbranch=getnum();
  195.                 if (!getlex(SEMI)) serror("Missing ';' after branch list");
  196.         }
  197.  
  198.  
  199. #ifdef COMPAT2
  200.         /* read suffix. Only in release 2 format */
  201.         if (getkey(Ksuffix)) {
  202.                 if (nexttok==STRING) {
  203.                         readstring(); nextlex(); /*through away the suffix*/
  204.                 } elsif(nexttok==ID) {
  205.                         nextlex();
  206.                 }
  207.                 if (!getlex(SEMI)) serror("Missing ';' after %s",Ksuffix);
  208.         }
  209. #endif
  210.  
  211.         if (!getkey(Kaccess)) fatserror("Missing access list");
  212.         while (id=getid()) {
  213.                 newaccess = (struct access *)talloc(sizeof(struct access));
  214.                 newaccess->login = id;
  215.                 newaccess->nextaccess = nil;
  216.                 if (AccessList == nil) {
  217.                         AccessList=LastAccess=newaccess;
  218.                 } else {
  219.                         LastAccess=LastAccess->nextaccess=newaccess;
  220.                 }
  221.         }
  222.         if (!getlex(SEMI)) serror("Missing ';' after access list");
  223.  
  224.         if (!getkey(Ksymbols)) fatserror("Missing symbols");
  225.         while (id = getid()) {
  226.                 if (!getlex(COLON))
  227.                         serror("Missing ':' in symbolic name definition");
  228.                 if (!(delta=getnum())) {
  229.                         serror("Missing number in symbolic name definition");
  230.                 } else { /*add new pair to association list*/
  231.                         newassoc=(struct assoc *)talloc(sizeof(struct assoc));
  232.                         newassoc->symbol=id;
  233.                         newassoc->delta=delta;
  234.                         newassoc->nextassoc=nil;
  235.                         if (Symbols == nil) {
  236.                                 Symbols=LastSymbol=newassoc;
  237.                         } else {
  238.                                 LastSymbol=LastSymbol->nextassoc=newassoc;
  239.                         }
  240.                 }
  241.         }
  242.         if (!getlex(SEMI)) serror("Missing ';' after symbolic names");
  243.  
  244.         if (!getkey(Klocks)) serror("Missing locks");
  245.         while (id = getid()) {
  246.                 if (!getlex(COLON))
  247.                         serror("Missing ':' in lock");
  248.                 if (!(delta=getnum())) {
  249.                         serror("Missing number in lock");
  250.                 } else { /*add new pair to lock list*/
  251. #                       ifdef SYNDB
  252.                         if ((countnumflds(delta->num)%2)!=0)
  253.                                 serror("Delta number required for lock");
  254. #                       endif
  255.                         newlock=(struct lock *)talloc(sizeof(struct lock));
  256.                         newlock->login=id;
  257.                         newlock->delta=delta;
  258.                         newlock->nextlock=nil;
  259.                         if (Locks == nil) {
  260.                                 Locks=LastLock=newlock;
  261.                         } else {
  262.                                 LastLock=LastLock->nextlock=newlock;
  263.                         }
  264.                 }
  265.         }
  266.         if (!getlex(SEMI)) serror("Missing ';' after locks");
  267.         if (!getkey(Kstrict)) {
  268.                 StrictLocks = false;
  269.         } else {
  270.                 StrictLocks = true;
  271.                 if (!getlex(SEMI)) serror("Missing ';' after keyword %s",Kstrict);
  272.         }
  273.         if (getkey(Kcomment) && (nexttok==STRING)) {
  274.                 VOID savestring(Commleader,COMMLENGTH);nextlex();
  275.                 Comment=Commleader;
  276.                 if (!getlex(SEMI)) serror("Missing ';' after %s",Kcomment);
  277.         }
  278. }
  279.  
  280.  
  281.  
  282. getdelta()
  283. /* Function: reads a delta block.
  284.  * returns false if the current block does not start with a number.
  285.  */
  286. {
  287.         register struct hshentry * Delta, * num;
  288.         struct branchhead * LastBranch, * NewBranch;
  289.  
  290.         if (!(Delta=getnum())) return false;
  291. #       ifdef SYNDB
  292.         if ((countnumflds(Delta->num)%2)!=0)
  293.                 serror("Delta number required");
  294. #       endif
  295.  
  296.         hshenter = false; /*Don't enter dates into hashtable*/
  297.         Delta->date = getkeyval(Kdate, NUM, false);
  298.         hshenter=true;    /*reset hshenter for revision numbers.*/
  299.  
  300.         Delta->author = getkeyval(Kauthor, ID, false);
  301.  
  302.         Delta->state = getkeyval(Kstate, ID, true);
  303.  
  304.         if (!getkey(Kbranches)) fatserror("Missing branches");
  305.         Delta->branches = LastBranch=nil;
  306.         while (num=getnum()) {
  307. #               ifdef SYNDB
  308.                 if ((countnumflds(num->num)%2)!=0)
  309.                         serror("Delta number required");
  310. #               endif
  311.                 NewBranch = (struct branchhead *)talloc(sizeof(struct branchhead));
  312.                 NewBranch->hsh = num;
  313.                 NewBranch->nextbranch = nil;
  314.                 if (LastBranch == nil) {
  315.                         Delta->branches=LastBranch=NewBranch;
  316.                 } else {
  317.                         LastBranch=LastBranch->nextbranch=NewBranch;
  318.                 }
  319.         }
  320.         if (!getlex(SEMI)) serror("Missing ';' after branches");
  321.  
  322.         if (!getkey(Knext)) fatserror("Missing next");
  323.         Delta->next=num=getnum();
  324. #       ifdef SYNDB
  325.         if (num&&((countnumflds(num->num)%2)!=0))
  326.                 serror("Delta number required");
  327. #       endif
  328.         if (!getlex(SEMI)) serror("Missing ';' after next");
  329.         Delta->log=Delta->lockedby = nil;
  330.         Delta->selector = '\0';
  331.         TotalDeltas++;
  332.         return (true);
  333. }
  334.  
  335.  
  336. gettree()
  337. /* Function: Reads in the delta tree with getdelta(), then
  338.  * updates the lockedby fields.
  339.  */
  340. {       struct lock * currlock;
  341.         while (getdelta());
  342.         currlock=Locks;
  343.         while (currlock) {
  344.                 currlock->delta->lockedby = currlock->login;
  345.                 currlock = currlock->nextlock;
  346.         }
  347. }
  348.  
  349.  
  350. getdesc(prdesc)
  351. int  prdesc;
  352. /* Function: read in descriptive text
  353.  * nexttok is not advanced afterwards.
  354.  * if prdesc==true, the text is printed to stdout.
  355.  */
  356. {
  357.  
  358.         if (!getkey(Kdesc) || (nexttok!=STRING)) fatserror("Missing descriptive text");
  359.         if (prdesc)
  360.                 printstring();  /*echo string*/
  361.         else    readstring();   /*skip string*/
  362. }
  363.  
  364.  
  365.  
  366.  
  367.  
  368.  
  369. char * getkeyval(keyword, token, optional)
  370. enum tokens token; char * keyword; int optional;
  371. /* reads a pair of the form
  372.  * <keyword> <token> ;
  373.  * where token is one of <id> or <num>. optional indicates whether
  374.  * <token> is optional. A pointer to
  375.  * the acutal character string of <id> or <num) is returned.
  376.  * Getkeyval terminates the program on missing keyword or token, continues
  377.  * on missing ;.
  378.  */
  379. {
  380.         register char * val;
  381.  
  382.         if (!getkey(keyword)) {
  383.                 fatserror("Missing %s", keyword);
  384.         }
  385.         if (nexttok==token) {
  386.                 val = NextString;
  387.                 nextlex();
  388.         } else {
  389.                 if (!optional) {fatserror("Missing %s", keyword); }
  390.                 else val = nil;
  391.         }
  392.         if (!getlex(SEMI)) serror("Missing ';' after %s",keyword);
  393.         return(val);
  394. }
  395.  
  396.  
  397.  
  398.  
  399. putadmin(fout)
  400. register FILE * fout;
  401. /* Function: Print the <admin> node read with getadmin() to file fout.
  402.  * Assumption: Variables AccessList, Symbols, Locks, StrictLocks,
  403.  * and Head have been set.
  404.  */
  405. {       struct assoc  * curassoc;
  406.         struct lock   * curlock;
  407.         struct access * curaccess;
  408.         register char * sp;
  409.  
  410.         VOID fputs(Khead,fout); VOID fputs("     ",fout);
  411.         if (Head) VOID fputs(Head->num,fout);
  412.  
  413.         VOID fprintf(fout,";\n%s   ",Kbranch);
  414.         if (Dbranch) VOID fputs(Dbranch->num,fout);
  415.  
  416.         VOID fprintf(fout,";\n%s  ",Kaccess);
  417.         curaccess = AccessList;
  418.         if (curaccess==nil) VOID putc(' ',fout);
  419.         while (curaccess) {
  420.                VOID putc(' ',fout);
  421.                VOID fputs(curaccess->login,fout);
  422.                curaccess = curaccess->nextaccess;
  423.         }
  424.         VOID fprintf(fout,";\n%s ",Ksymbols);
  425.         curassoc = Symbols;
  426.         if (curassoc==nil) VOID putc(' ',fout);
  427.         while (curassoc) {
  428.                VOID fprintf(fout," %s:%s",curassoc->symbol, curassoc->delta->num);
  429.                curassoc = curassoc->nextassoc;
  430.         }
  431.         VOID fprintf(fout,";\n%s   ",Klocks);
  432.         curlock = Locks;
  433.         if (curlock==nil) VOID putc(' ',fout);
  434.         while (curlock) {
  435.                VOID fprintf(fout," %s:%s",curlock->login, curlock->delta->num);
  436.                curlock = curlock->nextlock;
  437.         }
  438.         if (StrictLocks) VOID fprintf(fout,"; %s",Kstrict);
  439.         VOID fprintf(fout,";\n%s  %c",Kcomment,SDELIM);
  440.         if((sp=Comment)!=nil) {
  441.                while (*sp) if (putc(*sp++,fout)==SDELIM) VOID putc(SDELIM,fout);
  442.         }
  443.         VOID fprintf(fout,"%c;\n\n",SDELIM);
  444. }
  445.  
  446.  
  447.  
  448.  
  449. putdelta(node,fout)
  450. register struct hshentry * node;
  451. register FILE * fout;
  452. /* Function: prints a <delta> node to fout;
  453.  */
  454. {      struct branchhead * nextbranch;
  455.  
  456.         if (node == nil) return;
  457.  
  458.         VOID fprintf(fout,"\n%s\n",node->num);
  459.         VOID fprintf(fout,"%s     %s;  %s %s;  %s ",
  460.                 Kdate,node->date,Kauthor,node->author,Kstate);
  461.         if (node->state!=nil) VOID fputs(node->state,fout);
  462.         VOID fputs(";\nbranches",fout);
  463.         nextbranch = node->branches;
  464.         if (nextbranch==nil) VOID putc(' ',fout);
  465.         while (nextbranch) {
  466.                VOID putc(' ',fout);
  467.                VOID fputs(nextbranch->hsh->num,fout);
  468.                nextbranch = nextbranch->nextbranch;
  469.         }
  470.  
  471.         VOID fprintf(fout,";\n%s     ",Knext);
  472.         if (node->next!=nil) VOID fputs(node->next->num,fout);
  473.         VOID fputs(";\n",fout);
  474.  
  475. }
  476.  
  477.  
  478.  
  479.  
  480. puttree(root,fout)
  481. struct hshentry * root;
  482. register FILE * fout;
  483. /* Function: prints the delta tree in preorder to fout, starting with root.
  484.  */
  485. {       struct branchhead * nextbranch;
  486.  
  487.         if (root==nil) return;
  488.  
  489.         if (root->selector !=DELETE)putdelta(root,fout);
  490.         /* selector DELETE means deleted; set by rcs -o */
  491.  
  492.         puttree(root->next,fout);
  493.  
  494.         nextbranch = root->branches;
  495.         while (nextbranch) {
  496.              puttree(nextbranch->hsh,fout);
  497.              nextbranch = nextbranch->nextbranch;
  498.         }
  499. }
  500.  
  501.  
  502.  
  503. int putdtext(num,log,srcfilename,fout)
  504. char * num, * log, * srcfilename; FILE * fout;
  505. /* Function: write a deltatext-node to fout.
  506.  * num points to the deltanumber, log to the logmessage, and
  507.  * sourcefile contains the text. Doubles up all SDELIMs in both the
  508.  * log and the text; Makes sure the log message ends in \n.
  509.  * returns false on error.
  510.  */
  511. {
  512.         register char * sp;
  513.     register int c;
  514.         register FILE * fin;
  515.  
  516.         VOID fprintf(fout,DELNUMFORM,num,Klog);
  517.         /* put log */
  518.         VOID putc(SDELIM,fout);
  519.         sp=log;
  520.         while (*sp) if (putc(*sp++,fout)==SDELIM) VOID putc(SDELIM,fout);
  521.         if (*(sp-1)!='\n') VOID putc('\n', fout); /*append \n if necessary*/
  522.         /* put text */
  523.         VOID fprintf(fout, "%c\n%s\n%c",SDELIM,Ktext,SDELIM);
  524.         if ((fin=fopen(srcfilename,"r"))==NULL) {
  525.                 error("Can't open source file %s",srcfilename);
  526.                 return false;
  527.         }
  528.         while ((c=fgetc(fin))!=EOF) {
  529.                 if (c==SDELIM) VOID putc(SDELIM,fout);   /*double up SDELIM*/
  530.                 VOID putc(c,fout);
  531.         }
  532.         VOID putc(SDELIM,fout); VOID putc('\n',fout);
  533.         VOID fclose(fin);
  534.         return true;
  535. }
  536.  
  537.  
  538.  
  539. #ifdef SYNTEST
  540.  
  541. main(argc,argv)
  542. int argc; char * argv[];
  543. {
  544.  
  545.         cmdid = "syntest";
  546.         if (argc<2) {
  547.                 VOID fputs("No input file\n",stderr);
  548.                 exit(-1);
  549.         }
  550.         if ((finptr=fopen(argv[1], "r")) == NULL) {
  551.                 faterror("Can't open input file %s\n",argv[1]);
  552.         }
  553.         Lexinit();
  554.         getadmin();
  555.         putadmin(stdout);
  556.  
  557.         gettree();
  558.         puttree(Head,stdout);
  559.  
  560.         getdesc(true);
  561.  
  562.         if (nextlex(),nexttok!=EOFILE) {
  563.                 fatserror("Syntax error");
  564.         }
  565.         exit(0);
  566. }
  567.  
  568.  
  569. cleanup(){}
  570. /*dummy*/
  571.  
  572.  
  573. #endif
  574.  
  575.